package com.xzzz.irda.guardcat.server.repos.mysql;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.xzzz.common.base.pojo.PageRes;
import com.xzzz.common.base.pojo.R;
import com.xzzz.common.base.util.BeanUtil;
import com.xzzz.common.base.util.DateUtils;
import com.xzzz.common.dblog.LogService;
import com.xzzz.common.dblog.pojo.LevelCountRes;
import com.xzzz.common.dblog.pojo.LogEntity;
import com.xzzz.common.dblog.pojo.LogSearchReq;
import com.xzzz.irda.guardcat.server.log.pojo.LogLevelLineRes;
import com.xzzz.irda.guardcat.server.log.pojo.LogLevelPieRes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 【Server】日志[MySQL]
 */
@Slf4j
@RestController
@RequestMapping("/guardcat/log")
public class LogControllerInMySQL {

    @Autowired
    private LogService logService;

    /**
     * 分词功能
     *
     * @return 分词结果集合
     */
    @PostMapping("/analyze")
    public R<?> analyze(@RequestBody String body) {
        Map<String, String> map = new HashMap<>();
        map.put("term", "当前环境日志保存介质为MySQL, 无法查看分词");
        return R.ok(CollUtil.newArrayList(map));
    }

    /**
     * 日志分页搜索
     *
     * @param pageNum    当前页
     * @param pageSize   每页行数
     * @param beginDate  开始时间
     * @param endDate    结束时间
     * @param logLevel   日志级别
     * @param message    匹配的日志内容
     * @param notMessage 排除的日志内容
     * @param appName    应用名称,SpringBoot的应用名称
     * @param traceId    追踪ID
     */
    @GetMapping("/page")
    public R<PageRes<Map<String, String>>> page(
            @RequestParam Integer pageNum,
            @RequestParam Integer pageSize,
            @RequestParam(required = false) String appName,
            @RequestParam(required = false) String beginDate,
            @RequestParam(required = false) String endDate,
            @RequestParam(required = false) String logLevel,
            @RequestParam(required = false) String traceId,
            @RequestParam(required = false) String message,
            @RequestParam(required = false) String notMessage
    ) {
        long start = System.currentTimeMillis();
        log.debug("查询日志分页");
        LogSearchReq search = new LogSearchReq();
        search.setAppName(appName);
        search.setMessage(message);
        search.setNotMessage(notMessage);
        search.setPageNum(pageNum);
        search.setPageSize(pageSize);
        search.setLevel(logLevel);
        search.setTraceId(traceId);

        PageRes<LogEntity> pageRes = logService.search(search);
        PageRes<Map<String, String>> res = BeanUtil.toObj(pageRes, PageRes.class);
        List<Map<String, String>> dataList = new ArrayList<>();
        for (LogEntity log : pageRes.getDatas()) {
            Map<String, String> data = new HashMap<>();
            data.put("score", "0");
            data.put("datetime", DateUtils.format(log.getDatetime(), DatePattern.NORM_DATETIME_MS_PATTERN));
            data.put("level", log.getLevel());
            data.put("message", log.getMessage());
            data.put("traceId", log.getTraceId());
            data.put("spanId", log.getSpanId());
            data.put("clazz", log.getClassName());
            data.put("thread", log.getThread());
            data.put("appName", log.getAppName());
            data.put("hostName", log.getHostName());

            dataList.add(data);
        }
        res.setDatas(dataList);
        res.setTook(System.currentTimeMillis() - start);

        return R.ok(res);
    }

    /**
     * 日志饼图
     *
     * @return 饼图
     */
    @GetMapping("/chart/level/pie")
    public R<List<LogLevelPieRes>> levelPie(@RequestParam(required = false) String appName) {
        log.debug("查询日志饼图");
        List<LevelCountRes> dataList = logService.countGroupByLevel(appName);
        List<LogLevelPieRes> allLevel = new ArrayList<>();
        for (LevelCountRes data : dataList) {
            LogLevelPieRes level = new LogLevelPieRes();
            level.setLevel(data.getLevel());
            level.setName(String.format("%s(%d)", data.getLevel(), data.getCount()));
            level.setValue(data.getCount());
            allLevel.add(level);
        }
        return R.ok(allLevel);
    }

    /**
     * 日志多轴折线图
     *
     * @return 折线图
     */
    @GetMapping("/chart/level/line")
    public R<LogLevelLineRes> levelLine(@RequestParam(required = false) String appName) {
        // 每5分钟聚合
        final int interval = 5 * 60 * 1000;
        log.debug("查询日志折线图");
        long cur = System.currentTimeMillis();
        cur = cur - cur % interval;

        Date endTime = DateUtils.date(cur + interval);
        Date startTime = DateUtil.offsetDay(endTime, -1);
        long endTimestamp = cur + interval;
        long startTimestamp = DateUtils.toTimestamp(startTime);

        List<LevelCountRes> logList = logService.listGroupByLevel(appName, startTime, endTime);
        LogLevelLineRes line = new LogLevelLineRes();

        Set<String> dtList = new TreeSet<>();
        List<String> dList = new ArrayList<>();
        List<String> iList = new ArrayList<>();
        List<String> wList = new ArrayList<>();
        List<String> eList = new ArrayList<>();

        // 时间:日志列表
        Map<String, List<LevelCountRes>> map = logList.stream().collect(Collectors.groupingBy(LevelCountRes::getDt));

        for (long time = startTimestamp; time <= endTimestamp; time += interval) {
            dtList.add(DateUtils.format(DateUtils.date(time), DatePattern.NORM_DATETIME_PATTERN));
        }

        for (LevelCountRes data : logList) {
            dtList.add(data.getDt());
        }

        dtList.forEach(datetime -> {
            List<LevelCountRes> thisDtLevels = map.get(datetime);

            List<String> levels = CollUtil.newArrayList("DEBUG", "INFO", "WARN", "ERROR");

            if (CollUtil.isNotEmpty(thisDtLevels)) {
                for (LevelCountRes levelCountRes : thisDtLevels) {
                    if ("DEBUG".equals(levelCountRes.getLevel())) {
                        dList.add(String.valueOf(levelCountRes.getCount()));
                        levels.remove("DEBUG");
                    }
                    if ("INFO".equals(levelCountRes.getLevel())) {
                        iList.add(String.valueOf(levelCountRes.getCount()));
                        levels.remove("INFO");
                    }
                    if ("WARN".equals(levelCountRes.getLevel())) {
                        wList.add(String.valueOf(levelCountRes.getCount()));
                        levels.remove("WARN");
                    }
                    if ("ERROR".equals(levelCountRes.getLevel())) {
                        eList.add(String.valueOf(levelCountRes.getCount()));
                        levels.remove("ERROR");
                    }
                }
            }

            for (String level : levels) {
                if ("DEBUG".equals(level)) {
                    dList.add("0");
                }
                if ("INFO".equals(level)) {
                    iList.add("0");
                }
                if ("WARN".equals(level)) {
                    wList.add("0");
                }
                if ("ERROR".equals(level)) {
                    eList.add("0");
                }
            }

        });
        line.setDatetime(dtList.toArray(new String[dtList.size()]));
        line.setDebug(dList.toArray(new String[dList.size()]));
        line.setInfo(iList.toArray(new String[iList.size()]));
        line.setWarn(wList.toArray(new String[wList.size()]));
        line.setError(eList.toArray(new String[eList.size()]));
        line.setTitle("24小时日志, 按每【5】分钟聚合");

        return R.ok(line);
    }

    /**
     * 查询索引原文
     *
     * @param index 索引
     * @param id    文档ID
     * @return 索引原文
     */
    @GetMapping("/source")
    public R<?> source(String index, String id) {
        return R.ok("");
    }
}
